package com.baomibing.flow.example;

import com.baomibing.flow.constant.ActionTypeEnum;
import com.baomibing.flow.constant.NodeTypeEnum;
import com.baomibing.flow.dto.SysFlowDto;
import com.baomibing.flow.enginee.Process;
import com.baomibing.flow.enginee.*;
import com.baomibing.flow.execute.Execution;
import com.baomibing.flow.model.*;
import com.baomibing.flow.service.WorkFlowEnginee;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Example
 *
 * @author frog 2025/1/20 11:24
 * @version 1.0.0
 **/
@Component
public class Example {

    @Autowired private WorkFlowEnginee flowEngine;
    private WorkFlow build() {
        WorkFlow wf = new WorkFlow();
        StartNode start = new StartNode("start");
        TaskNode task = new TaskNode("提交辞职");
        task.setActionType(ActionTypeEnum.ANY);
        TransitionNode t1 = new TransitionNode(start, task);

        SubProcess s1 = new SubProcess(wf).source(start).target(task).action(t1);


        TaskNode approveTask = new TaskNode("辞职审批");
        approveTask.setActionType(ActionTypeEnum.ALL).withEntrusts(Lists.newArrayList("ning","wang","zhang"));
        TransitionNode approvet = new TransitionNode(task, task);

        SubProcess approveProcess = new SubProcess(wf).source(task).target(approveTask).action(approvet);



        ParallelNode pnode = new ParallelNode("并发");

        JoinNode tempJoin = new JoinNode("合并—" + approveTask.getName());
        List<SubProcess> joinTaskProcess = Lists.newArrayList();
        for (String s : approveTask.getEntrusts()) {
            TransitionNode t = new TransitionNode(approveTask, tempJoin, false, false);
            SubProcess sub = new SubProcess(wf).source(task).actor(s).target(tempJoin).action(t);
            joinTaskProcess.add(sub);
        }
        TaskJoinProcess taskJoinProcess = new TaskJoinProcess(wf);
        taskJoinProcess.setProcesses(joinTaskProcess);
        task.setChildProcess(taskJoinProcess);

        TransitionNode t2 = new TransitionNode(task, pnode);
        SubProcess s2 = new SubProcess(wf).source(task).target(pnode).action(t2);


        TaskNode resourceTask = new TaskNode("人力交接");
        resourceTask.withEntrusts(Lists.newArrayList("哈女士"));
        TransitionNode pt2 = new TransitionNode(pnode, resourceTask);
        SubProcess ps2 = new SubProcess(wf).source(pnode).target(resourceTask).action(pt2);


        TaskNode financeTask = new TaskNode("财务交接");
        financeTask.withEntrusts(Lists.newArrayList("王女士"));
        TransitionNode pt3 = new TransitionNode(pnode, financeTask);
        SubProcess ps3 = new SubProcess(wf).source(pnode).target(financeTask).action(pt3);

        TaskNode workTask = new TaskNode("工作交接");
        workTask.withEntrusts(Lists.newArrayList("韩先生"));
        TransitionNode pt4 = new TransitionNode(pnode, workTask);
        SubProcess ps4 = new SubProcess(wf).source(pnode).target(workTask).action(pt4);

        ParallelProcess pp = new ParallelProcess(wf).source(pnode);
        List<Process> processList = Lists.newArrayList( ps2, ps3, ps4);
        pp.setProcesses(processList);

        JoinNode joinNode = new JoinNode("合并");
        TransitionNode jt1 = new TransitionNode(resourceTask, joinNode);
        SubProcess js1 = new SubProcess(wf).source(resourceTask).target(joinNode).action(jt1);

        TransitionNode jt2 = new TransitionNode(financeTask, joinNode);
        SubProcess js2 = new SubProcess(wf).source(financeTask).target(joinNode).action(jt2);

        TransitionNode jt3 = new TransitionNode(workTask, joinNode);
        SubProcess js3 = new SubProcess(wf).source(workTask).target(joinNode).action(jt3);


        TaskNode auditTask = new TaskNode("总经理审批");
        auditTask.withEntrusts(Lists.newArrayList("刘总"));
        TransitionNode auditTrans = new TransitionNode(joinNode, auditTask);
        SubProcess js4 = new SubProcess(wf).source(joinNode).target(auditTask).action(auditTrans);
        JoinProcess jp = new JoinProcess(wf);
        jp.setTargetProcess(js4);
        List<SubProcess> joinSubProcess = Lists.newArrayList(js1, js2, js3);
        jp.setProcesses(joinSubProcess);


        EndNode end = new EndNode("结束");
        TransitionNode endTrans = new TransitionNode(auditTask, end);
        SubProcess endProcess = new SubProcess(wf).source(auditTask).target(end).action(endTrans);

        List<Process> allProcess = Lists.newArrayList();
        allProcess.add(s1);
        allProcess.add(approveProcess);
        allProcess.add(s2);
        allProcess.add(pp);
        allProcess.add(jp);
        allProcess.add(endProcess);

        wf.setProcesses(allProcess);

//        System.out.println("======process:");
//        String ss = JSONArray.toJSONString(allProcess, SerializerFeature.DisableCircularReferenceDetect);
//        System.out.println(ss);
//
//        WorkFlowEngine engine = new WorkFlowEngine();
//        List<Process> deprocess = new WorkFlowTransfer(wf).processDeserialize(ss);//engine.processDeserialize(ss, wf);
//
//        System.out.println("======de  process:");
//        String dess = JSONArray.toJSONString(deprocess, SerializerFeature.DisableCircularReferenceDetect);
//        System.out.println(dess);
//        wf.setProcesses(deprocess);
//
//        List<Process> serProcess = JSONArray.parseArray(ss, Process.class);
//
//        System.out.println("");
        wf.setStart(start).setEnd(end);
        return wf;
    }

    public void test() {


        WorkFlow wf = build();
        SysFlowDto flow = flowEngine.deploy(wf);

        String instanceId = flowEngine.doStartFlow(flow.getId(), Execution.createByNodeType(NodeTypeEnum.Start).setActor("ning"));
        Map<String, Execution> map1 = new HashMap<>();
        map1.put("辞职审批", Execution.createByNodeType(NodeTypeEnum.Task).setActor("ning"));
        WorkFlow f = flowEngine.doExecute(instanceId, map1);
        f.printCurrent();

        map1.put("辞职审批", Execution.createByNodeType(NodeTypeEnum.Task).setActor("wang"));
        f = flowEngine.doExecute(instanceId, map1);
        f.printCurrent();

        map1.put("辞职审批", Execution.createByNodeType(NodeTypeEnum.Task).setActor("zhang"));
        f = flowEngine.doExecute(instanceId, map1);
        f.printCurrent();

//        wf.doExecute(map1);

//        wf.setStart(start);

//        wf.printCurrent();

//        wf.doStart(Execution.createByNode(start).setActor("ning"));
//        flowEngine
    }

    public void test0( String id) {
        Map<String, Execution> map1 = new HashMap<>();
        map1.put("辞职", Execution.createByNodeType(NodeTypeEnum.Task).setActor("ning"));
        WorkFlow f = flowEngine.doExecute(id, map1);
        f.printCurrent();

        map1.put("辞职", Execution.createByNodeType(NodeTypeEnum.Task).setActor("wang"));
        f = flowEngine.doExecute(id, map1);
        f.printCurrent();

        map1.put("辞职", Execution.createByNodeType(NodeTypeEnum.Task).setActor("zhang"));
        f = flowEngine.doExecute(id, map1);
        f.printCurrent();
    }

    public void test1( String id) {
        Map<String, Execution> map3 = new HashMap<>();
        map3.put("人力交接", Execution.createByNodeType(NodeTypeEnum.Task).setActor("哈女士"));
        map3.put("财务交接", Execution.createByNodeType(NodeTypeEnum.Task).setActor("王女士"));
        map3.put("工作交接", Execution.createByNodeType(NodeTypeEnum.Task).setActor("韩先生"));
        WorkFlow f = flowEngine.doExecute(id, map3);
        f.printCurrent();
    }

    public void test2( String id) {
        Map<String, Execution> map5 = new HashMap<>();
        map5.put("总经理审批", Execution.createByNodeType(NodeTypeEnum.Task).setActor("刘总"));
        WorkFlow f = flowEngine.doExecute(id, map5);
        f.printCurrent();
    }

    public void reject( String id) {
        Map<String, Execution> map = new HashMap<>();
        map.put("结束", Execution.createByNodeType(NodeTypeEnum.End).setActor("ning"));
        WorkFlow f = flowEngine.doReject(id, map);
        f.printCurrent();
    }

    public void reject1( String id) {
        Map<String, Execution> map = new HashMap<>();
        map.put("总经理审批", Execution.createByNodeType(NodeTypeEnum.Task).setActor("刘总"));
        WorkFlow f = flowEngine.doReject(id, map);
        f.printCurrent();
    }

    public void reject2( String id) {
        Map<String, Execution> map = new HashMap<>();
        map.put("工作交接", Execution.createByNodeType(NodeTypeEnum.Task).setActor("韩先生"));
        WorkFlow f = flowEngine.doReject(id, map);
        f.printCurrent();
    }
}
